\documentclass[12pt]{article}

\usepackage{sbc-template}
\usepackage{graphicx,url} 
\usepackage[brazilian]{babel}
\usepackage[utf8]{inputenc} 
\usepackage[T1]{fontenc}
\usepackage{algorithmic}
\usepackage{algorithm}

\usepackage{listings}

\lstset{
language=VHDL,
basicstyle=\tiny\ttfamily}

\sloppy

\author{Artur Gontijo, Henrique F. Baggio, Lucas Katayama, Victor Macedo}

\address{Engenharia de Computação\\ Universidade Estadual de Campinas - Unicamp\\
Campinas, São Paulo, Brasil
}

\title{MC613 - Projeto Final \\ Batalha Naval}

\begin{document} 

\maketitle

%\begin{abstract}
%\end{abstract}

\section{Introdução}
Batalha naval é um jogo de tabuleiro de dois jogadores, os quais têm de adivinhar em que quadrados estão os navios do oponente. Embora o primeiro jogo em tabuleiro foi comercializado e publicado pela Milton Bradley Company em 1931, o jogo fora originalmente jogado com lápis e papel.

O jogo original é jogado em duas tabelas para cada jogador - uma que representa a disposição dos barcos do jogador, e outra que representa a do oponente. Em uma tabela o jogador coloca os seus navios e, em outra, registra os tiros no oponente.

Neste projeto, implementamos o jogo Batalha Naval utilizando duas placas FPGA DE1 da Altera, onde cada jogador usa uma placa, com seus respectivos mouse e teclado.
 
\section{Funcionamento geral}
As placas se comunicam através de suas interfaces GPIO, ligadas por dois cabos paralelos, um para a entrada e outro para a saída de dados. Optamos por ligá-las de forma que cada placa processe as entradas e saídas do seu usuário, enviando a jogada para a outra e recebendo as respostas. Assim, nelas roda exatamente o mesmo circuito, e evitamos ter diferenças do tipo mestre-escravo.

Uma das placas é a primeira a jogar, e definimos isso simplesmente através de uma das chaves \emph{toggle switch}, que fica ligada na placa que será a primeira a jogar. Usamos também um \emph{push botton} para \textbf{start/reset} em cada placa, que deve ser acionado no início do jogo e também para reiniciar quando necessário.

Cada jogador tem, na sua tela, a visão do seu tabuleiro e o que já foi desvendado do oponente, como podemos ver na figura \ref{fig:board2}. Na sua vez, um jogador escolhe uma posição no tabuleiro do oponente para atirar, clicando com o mouse. Então ele recebe uma resposta que indica se acertou ou não algum barco do adversário. Um acerto é representado por um quadrado vermelho, enquanto que um erro é um quadrado azul. O jogo segue então, alternando tiros de cada jogador, até que um acerte completamente todos os barcos do oponente. Quando o jogo termina é apresentada uma tela indicando se ele venceu ou perdeu a disputa.

\begin{figure}
\includegraphics[width=\textwidth]{./images/board_2.png} 
\caption{Visão da tela durante o jogo \label{fig:board2}}
\end{figure}

\begin{figure}
\includegraphics[width=0.5\textwidth]{./images/win.png}
\includegraphics[width=0.5\textwidth]{./images/lose.png}
\caption{Visão das telas do vencedor e do perdedor \label{fig:winlose}}
\end{figure}


\section{Componentes}
O sistema é composto por 3 componentes: um módulo para a interface com o mouse, outro para o monitor e uma central responsável pelo processamento das entradas/saídas e pela comunicação com a outra placa. As interfaces com o mouse e monitor foram implementadas de modo a usar os mesmos controladores utilizados durante os laboratórios da disciplina, \texttt{vgacon e mouse-ctrl}, e são bem simples, necessitando de pouco código.

Já a Central é mais complexa, controlando todo o sistema enquanto alterna entre quatro operações principais: enviar tiro, receber resposta, receber tiro, enviar resposta. Em cada um dessas etapas os dados referentes às 3 interfaces de IO são atualizados.

\subsection{Comunicação entre placas}
O item mais complexo no sistema é a parte de comunicar as duas placas de forma a enviar e receber as informações referentes a cada jogada, seja do jogador ou do adversário. Como o clock entre as placas não é compartilhado, foi preciso implementar um \emph{handshake} para ser usado na troca de mensagens. Este usa, além de um canal de dados de 8 bits, sinais de controle extras, para sinalizar a disponibilidade de dados (\emph{ready}) e confirmar recebimento de dados (\emph{ack}). Cada placa tem um grupo desses sinais para entrada e outro para saída.

Assim, quando uma placa deve enviar uma informação para a outra, ela escreve no canal de dados, sinaliza a operação através do sinal ready e passa a esperar a confirmação da oponente pelo sinal ack. Por sua vez, a placa que está esperando por dados o faz até que o sinal ready seja ativado e, depois de ler os dados do canal, sinaliza o recebimento usando o ack. 

Esse ciclo de recebimento e envio de dados se repete durante todo o jogo. Para isso, utiliza-se uma máquina de estados finitos (FSM) representada na figura \ref{fig:fsm}, onde a transições dependem dos sinais ack e ready e da entrada da jogada pelo usuário.

\begin{figure}[!b]
\centering
\includegraphics[width=0.7\textwidth]{images/fsm.png} 
\caption{FSM da comunicação entre as placas \label{fig:fsm}}
\end{figure}

\section{Conclusões e Comentários}
Apesar de algumas dificuldades na etapa de implementação do sistema, conseguimos desenvolver o projeto e obter um jogo funcional. A comunicação entre as placas funcionou corretamente e os resultados foram bem próximos do esperado. Não conseguimos implementar corretamente apenas o desenho do tabuleiro pelo usuário no início do jogo, e por isso deixamos os tabuleiros estáticos.

O fato de termos que usar duas placas tornou o projeto mais complexo, mas ao mesmo tempo mais desafiador, pois exigiu implementações de conceitos que não foram vistos durante os laboratórios do semestre. Houve uma certa dificuldade em manipular uma máquina de estados tão grande e com muitos sinais de controle, ao mesmo tempo que se controlava os dispositivos de entrada e saída. 



\appendix
\section{Codigo da FSM}
A seguir, o trecho de \texttt{central.vhd} que implementa a máquina de estados do jogo.

\begin{lstlisting}
-- Game FSM
-- process the next state
process(CLOCK_27(0), reset, lose_other, lose_me)
begin
    if reset = '0' then -- reset
        state <= inicio;
    elsif (lose_other = '1') then
        state <= fim_jogo;
    elsif (lose_me = '1') then
        state <= fim_jogo;
    elsif rising_edge(CLOCK_27(0)) then
        case (state) is
            when inicio =>
                state <= put_barcos;
            when put_barcos=>
                if (put_barco = 14) then
                    case first is              
                        when '1' => state <= wait_data;
                        when '0' => state <= wait_shot;
                        when others => null;
                    end case;
                end if;
            when send_shot => -- we wait until the other read the data sent
                if (ack_other = '1') then
                    state <= wait_feedback;
                end if; 
            when wait_feedback => -- we wait until the other send new data
                if (ready_other = '1') then
                    state <= recv_feedback;
                end if;
            when recv_feedback =>
                if (ready_other = '0') then
                    state <= wait_shot;
                end if;
            when wait_shot => -- we wait until the other send new data
                if (ready_other = '1') then
                    state <= recv_shot;
                end if;
            when recv_shot =>
                if (data_ready = '1') then
                    state <= send_feedback;
                end if;
            when send_feedback => -- we wait until the other read the data sent
                if (ack_other = '1') then
                    state <= wait_data;
                end if;
            when wait_data => -- aqui espera o clique do mouse pra entao pegar a jogada
                if (click = '1') then
                    state <= send_shot;
                end if;
            when others => null;
        end case;
    end if;
end process;

-- process the outputs for eache FSM's state
process(CLOCK_27(0))
    variable x_me, y_me : integer range 0 to 15; -- coordenadas na matriz 
    variable x_other, y_other : integer range 0 to 15; -- coordenadas na matriz
begin
    if (rising_edge(CLOCK_27(0))) then
    case (state) is
        when inicio =>                     
            ready_me <= '0';
            ack_me <= '0';
            matriz<=matriz_inic;
            life_me <= 14;
            put_barco <= 0;
            lose_me <= '0';
            
        when put_barcos  =>
            x_me := conv_integer(x_mouse(7 downto 3)); -- the MSB is always zero
            y_me := conv_integer(y_mouse(7 downto 3));
            
            if (click = '1' and x_me >= 1 and x_me <= 6 and y_me >= 1 and y_me <= 10) then
                if (matriz(y_me)(x_me) /= "000") then
                    put_barco <= put_barco + 1;
                    matriz(y_me)(x_me) <= "000"; --preto
                end if;
            end if;
            
        when send_shot => -- send a shot to the other
            x_me := conv_integer(x_mouse(7 downto 3)); -- the MSB is always zero
            y_me := conv_integer(y_mouse(7 downto 3));
            
            if (x_me >= 9 and x_me <= 14 and y_me >= 1 and y_me <= 10) then
                data_me <= x_mouse(6 downto 3) & y_mouse(6 downto 3); -- dado que vou enviar pela rede
                ready_me <= '1';
            else 
                ready_me <= '0';
            end if;

        when wait_feedback =>
            ready_me <= '0';
            ack_me <= '0';
            
        when recv_feedback =>   
            -- indica agua (00) ou fogo (01) ou barco ja atingido (10)
            if (data_other(1 downto 0) = "01") then 
                matriz(y_me)(x_me) <= "100"; -- red
            elsif (data_other(1 downto 0) = "00") then
                matriz(y_me)(x_me) <= "001"; -- blue
            else
                null; -- "10"
            end if;
            
            ack_me <= '1';
            ready_me <= '0';
            
        when wait_shot =>
            ack_me <= '0';
            ready_me <= '0';
            
        when recv_shot =>          
            -- pego a jogada do adversario pela rede
            -- os dados sao sempre validos, pq ele verifica pra enviar
            x_other := conv_integer(data_other(7 downto 4)) - 8;
            y_other := conv_integer(data_other(3 downto 0));
            
            if (matriz(y_other)(x_other) = "000") then -- ve se tem um barco na minha parte
                matriz(y_other)(x_other) <= "100"; -- red
                water_me <= "01"; -- deu fogo
                life_me <= life_me - 1;
            elsif (matriz(y_other)(x_other) = "100") then 
                water_me <= "10";
            else
                water_me <= "00"; -- deu agua
            end if;
            
            ack_me <= '1';
            ready_me <= '0';
            data_ready <= '1'; -- posso mudar de estado
            
        when send_feedback =>
            if (life_me = 0) then
                lose_me <= '1';
            else
                data_me <= "000000" & water_me;
                ready_me <= '1';
                ack_me <= '0';
            end if;		
            
        when wait_data =>
            ready_me <= '0';
            ack_me <= '0';
            
        when fim_jogo =>
            if (lose_other = '1') then
                matriz <= matriz_win;
            else
                matriz <= matriz_lose;
            end if;
            
        when others =>
            null;
    end case;
    end if;
end process; 
\end{lstlisting}

%\bibliographystyle{sbc}
%\bibliography{references}

%------------------------------------------------------------------------- 


\end{document}

